﻿#ifndef MESSAGECHANNEL_H
#define MESSAGECHANNEL_H
#include <memory>

#include "signalslot.h"
#include "threadsafe.h"

class Message;

typedef std::wstring MessageType;


struct MessageException{
};

class MessageFactory{
public:
    virtual Message* CreateMessage(MessageType type) = 0;
};

typedef unsigned short ClientId;

struct REFLECTX_EXPORT Message{
public:
    ClientId source = 0;
    MessageType type;
    virtual ~Message(){};
    virtual void Serilize(DataOutputStream& s);
    virtual void UnSerilize(DataInputStream& s) throw (MessageException);
public:
    static ByteArray Serilize(Message *message);
    static Message *UnSerilize(ByteArray & str) throw (MessageException);
    static void RegisterFactory(MessageFactory* factory);
    static void UnRegisterFactory(MessageFactory* factory);
};
typedef std::shared_ptr<Message> MessagePtr;

class REFLECTX_EXPORT Channel:public ThreadSafe::ThreadSafeBase{
public:
    Channel();
    ~Channel();

    void Bind(int port);
    void ConnectTo(std::string ip,int port);
    void close();
    void abort(ClientId id);

    void SendMessage(Message* message);
    void SendMessage(Message* message,ClientId id);
    bool hasMessage() const;
    MessagePtr nextMessage();

public:
    Signal<> NewMessage;
    Signal<ClientId> NewClient;
    Signal<ClientId> ClientDisconnected;

private:
    void slotOnClientMessage(ClientId id);
    void slotOnNewConnection();
    void slotOnHostMessage();
    void slotOnHostDisconnected();
private:
    struct Private;
    std::unique_ptr<Private> _P;
};

#endif // MESSAGECHANNEL_H
